package com.config;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.io.Writer;
import java.util.Properties;

import org.apache.log4j.Logger;


/**
 * �?��配置的读取位置，允许配置文件不存�?
 * 
 * @author chengping 2013-7-25
 * 
 * @version v1.0.0
 *  
 */
public class ClientConfiguration {
	private static final String[] DEFAULT_RESOURCE = { "miniType.properties" };
	private static volatile boolean INIT = false;
	private static Properties props;
	private static String[] RESOURCES = DEFAULT_RESOURCE;
	private static Logger log = Logger.getLogger(ClientConfiguration.class);

	/**
	 * 获取配置信息，找不到key时返回null
	 * @param key 配置�?
	 * @return 配置�?
	 */
	public static String get(String key) {
		return props.getProperty(key);
	}

	/**
	 * 获取配置信息，找不到key时返回默认�?
	 * @param key 配置�?
	 * @param defaultValue 默认�?
	 * @return 配置�?
	 */
	public static String get(String key, String defaultValue) {
		return props.getProperty(key, defaultValue);
	}

	/**
	 * Get the value of the <code>name</code> property as a
	 * <code>boolean</code> . If no such property is specified, or if the
	 * specified value is not a valid <code>boolean</code>, then
	 * <code>defaultValue</code> is returned.
	 * 
	 * @param name
	 *            property name.
	 * @param defaultValue
	 *            default value.
	 * @return property value as a <code>boolean</code>, or
	 *         <code>defaultValue</code>.
	 */
	public static boolean getBoolean(String name, boolean defaultValue) {
		String valueString = get(name);
		if ("true".equals(valueString))
			return true;
		if ("false".equals(valueString))
			return false;
		return defaultValue;
	}

	/**
	 * Get the value of the <code>name</code> property as a <code>float</code>.
	 * If no such property is specified, or if the specified value is not a
	 * valid <code>float</code>, then <code>defaultValue</code> is
	 * returned.
	 * 
	 * @param name
	 *            property name.
	 * @param defaultValue
	 *            default value.
	 * @return property value as a <code>float</code>, or
	 *         <code>defaultValue</code>.
	 */
	public static float getFloat(String name, float defaultValue) {
		String valueString = get(name);
		if (valueString == null)
			return defaultValue;
		try {
			return Float.parseFloat(valueString);
		} catch (NumberFormatException e) {
			return defaultValue;
		}
	}

	/**
	 * Get the value of the <code>name</code> property as an <code>int</code>.
	 * 
	 * If no such property exists, or if the specified value is not a valid
	 * <code>int</code>, then <code>defaultValue</code> is returned.
	 * 
	 * @param name
	 *            property name.
	 * @param defaultValue
	 *            default value.
	 * @return property value as an <code>int</code>, or
	 *         <code>defaultValue</code>.
	 */
	public static int getInt(String name, int defaultValue) {
		String valueString = get(name);
		if (valueString == null)
			return defaultValue;
		try {
			return Integer.parseInt(valueString);
		} catch (NumberFormatException e) {
			return defaultValue;
		}
	}

	/**
	 * Get the value of the <code>name</code> property as a <code>long</code>.
	 * If no such property is specified, or if the specified value is not a
	 * valid <code>long</code>, then <code>defaultValue</code> is returned.
	 * 
	 * @param name
	 *            property name.
	 * @param defaultValue
	 *            default value.
	 * @return property value as a <code>long</code>, or
	 *         <code>defaultValue</code>.
	 */
	public static long getLong(String name, long defaultValue) {
		String valueString = get(name);
		if (valueString == null)
			return defaultValue;
		try {
			return Long.parseLong(valueString);
		} catch (NumberFormatException e) {
			return defaultValue;
		}
	}

	/**
	 * 在项目启动前先初始化该对象读取配置文件�?
	 * 
	 */
	public static void init() {
		if (INIT) {
			return;
		}
		props = new Properties();
		InputStream in = null;
		try {
			for (String resource : RESOURCES) {
				log.info("load resource:"+resource);
				in = ClientConfiguration.class.getClassLoader().getResourceAsStream(
						resource);// 读取工程下的配置文件
				props.load(in);
				in.close();
			}
			INIT = true;
//			StringBuilderWriter sbw = new StringBuilderWriter();
//			props.list(new PrintWriter(sbw));
//			LOG.info(sbw.toString());
//			validate();
		} catch (Exception e) {
			INIT = false;
			clear();
			log.warn("Failed to init conf, resource:" + RESOURCES);
		}finally{
			if(in!=null){
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 初始化配置文件信�?
	 * @param resource 配置文件集合
	 */
	public static void init(String[] resource) {
		RESOURCES = resource;
		init();
	}
	
	/**
	 * 清除配置信息
	 */
	public static void clear() {
		props.clear();
	}
}

/**
 * {@link Writer} implementation that outputs to a {@link StringBuilder}.
 * <p>
 * <strong>NOTE:</strong> This implementation, as an alternative to
 * <code>java.io.StringWriter</code>, provides an <i>un-synchronized</i>
 * (i.e. for use in a single thread) implementation for better performance. For
 * safe usage with multiple {@link Thread}s then
 * <code>java.io.StringWriter</code> should be used.
 * 
 * @version $Id: StringBuilderWriter.java 1304052 2012-03-22 20:55:29Z ggregory $
 * @since 2.0
 */
//class StringBuilderWriter extends Writer implements Serializable {
//
//	/**
//	 * 序列�?
//	 */
//	private static final long serialVersionUID = 1L;
//	
//	private final StringBuilder builder;
//
//	/**
//	 * Construct a new {@link StringBuilder} instance with default capacity.
//	 */
//	public StringBuilderWriter() {
//		this.builder = new StringBuilder();
//	}
//
//	/**
//	 * Construct a new {@link StringBuilder} instance with the specified
//	 * capacity.
//	 * 
//	 * @param capacity
//	 *            The initial capacity of the underlying {@link StringBuilder}
//	 */
//	public StringBuilderWriter(int capacity) {
//		this.builder = new StringBuilder(capacity);
//	}
//
//	/**
//	 * Construct a new instance with the specified {@link StringBuilder}.
//	 * 
//	 * @param builder
//	 *            The String builder
//	 */
//	public StringBuilderWriter(StringBuilder builder) {
//		this.builder = builder != null ? builder : new StringBuilder();
//	}
//
//	/**
//	 * Append a single character to this Writer.
//	 * 
//	 * @param value
//	 *            The character to append
//	 * @return This writer instance
//	 */
//	@Override
//	public Writer append(char value) {
//		builder.append(value);
//		return this;
//	}
//
//	/**
//	 * Append a character sequence to this Writer.
//	 * 
//	 * @param value
//	 *            The character to append
//	 * @return This writer instance
//	 */
//	@Override
//	public Writer append(CharSequence value) {
//		builder.append(value);
//		return this;
//	}
//
//	/**
//	 * Append a portion of a character sequence to the {@link StringBuilder}.
//	 * 
//	 * @param value
//	 *            The character to append
//	 * @param start
//	 *            The index of the first character
//	 * @param end
//	 *            The index of the last character + 1
//	 * @return This writer instance
//	 */
//	@Override
//	public Writer append(CharSequence value, int start, int end) {
//		builder.append(value, start, end);
//		return this;
//	}
//
//	/**
//	 * Closing this writer has no effect.
//	 */
//	@Override
//	public void close() {
//	}
//
//	/**
//	 * Flushing this writer has no effect.
//	 */
//	@Override
//	public void flush() {
//	}
//
//	/**
//	 * Write a String to the {@link StringBuilder}.
//	 * 
//	 * @param value
//	 *            The value to write
//	 */
//	@Override
//	public void write(String value) {
//		if (value != null) {
//			builder.append(value);
//		}
//	}
//
//	/**
//	 * Write a portion of a character array to the {@link StringBuilder}.
//	 * 
//	 * @param value
//	 *            The value to write
//	 * @param offset
//	 *            The index of the first character
//	 * @param length
//	 *            The number of characters to write
//	 */
//	@Override
//	public void write(char[] value, int offset, int length) {
//		if (value != null) {
//			builder.append(value, offset, length);
//		}
//	}
//
//	/**
//	 * Return the underlying builder.
//	 * 
//	 * @return The underlying builder
//	 */
//	public StringBuilder getBuilder() {
//		return builder;
//	}
//
//	/**
//	 * Returns {@link StringBuilder#toString()}.
//	 * 
//	 * @return The contents of the String builder.
//	 */
//	@Override
//	public String toString() {
//		return builder.toString();
//	}
//
//}
